package com.dq.service.sys.user.impl;

import com.alibaba.fastjson.JSONObject;
import com.dq.context.Constant;
import com.dq.controller.in.user.WxUserQuery;
import com.dq.domain.base.AbstractEntity;
import com.dq.domain.base.impl.BaseDaoImpl;
import com.dq.domain.sys.user.user.centre.UserCard;
import com.dq.domain.sys.user.user.centre.UserCardServiceProjectCentre;
import com.dq.domain.sys.user.user.centre.UserLable;
import com.dq.domain.sys.user.user.centre.UserLableCentre;
import com.dq.exception.customException.AdminException;
import com.dq.controller.in.request.WxUserAddRequest;
import com.dq.controller.in.base.BaseAdminQuery;
import com.dq.domain.org.Org;
import com.dq.domain.sys.user.user.base.SysUser;
import com.dq.domain.sys.user.user.WxUser;
import com.dq.repository.BaseRepositories;
import com.dq.service.org.OrgService;
import com.dq.service.sys.user.BossUserService;
import com.dq.service.sys.user.WxUserService;
import com.dq.utils.BeanNullUtil;
import com.dq.utils.EditCheckUtil;
import com.google.gson.Gson;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.*;

/**
 * @author liuhui
 * @date 2019/12/2 0002 14:34:06
 */
@Service
public class WxUserServiceImpl extends BaseRepositories implements WxUserService {

    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private BossUserService bossUserService;
    @Autowired
    private OrgService orgService;

    @Override
    public List<WxUser> wxUserList(WxUserQuery wxUserQuery) throws AdminException {
        wxUserQuery.format();


        Map<String, Object> query = createQuery(wxUserQuery);

        return dao.find(dao.query2Hql(WxUser.class, query), query);
    }
    @Override
    public Long wxUserCount(WxUserQuery wxUserQuery) throws AdminException {
        Map<String, Object> query = createQuery(wxUserQuery);


        return dao.count(dao.count2Hql(WxUser.class, query), query);
    }
    public Map<String, Object> createQuery(WxUserQuery wxUserQuery) throws AdminException {
        Map<String, Object> query = wxUserQuery.parseMap();

        List<Long> orgidsInList = new ArrayList<>();
        if(wxUserQuery.getOrgId() != null) {
            orgidsInList.add(wxUserQuery.getOrgId());
        }else {

            // 只显示负责门店信息
            List<Org> orgList = orgService.getListAllByUser();
            for (Org org : orgList) {
                orgidsInList.add(org.getId());
            }
        }
        if(orgidsInList.size() > 0) {
            query.put("section_id" + BaseDaoImpl.inSqlStr, orgidsInList);
            query.remove("orgId");
        }

        if(StringUtils.isNotBlank(wxUserQuery.getValue())) {
            Map<String, Object> keyQuery = new HashMap<>(16);
            keyQuery.put("userRealcName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(wxUserQuery.getValue()));
            keyQuery.put("cardNo", wxUserQuery.getValue());
            query.put("keyQuery" + BaseDaoImpl.orAndSqlStr, keyQuery);
            query.remove("value");
        }
        if(StringUtils.isNotBlank(wxUserQuery.getUserLableName())) {
            List<UserLableCentre> userLableCentreList =
                    userLableCentreRepository.findByDeletedFalseAndUserLableNameLikeAndUserLableType("%" + wxUserQuery.getUserLableName() + "%", UserLable.LableType.one);
            List<Long> userIds = new ArrayList<>();
            for (UserLableCentre userLableCentre : userLableCentreList) {
                userIds.add(userLableCentre.getSysUser().getId());
            }
            query.put("id" + BaseDaoImpl.inSqlStr, userIds);
            query.remove("userLableName");
        }
        if(StringUtils.isNotBlank(wxUserQuery.getUserRealcName())) {
            query.put("userRealcName" + BaseDaoImpl.likeSqlStr, BaseAdminQuery.likeSql(wxUserQuery.getUserRealcName()));
            query.remove("userRealcName");
        }

        if(wxUserQuery.getBeginPayTime() != null) {
            query.put("payTime" + BaseDaoImpl.gteSqlStr, wxUserQuery.getBeginPayTime());
            query.remove("beginPayTime");
        }
        if(wxUserQuery.getEndPayTime() != null) {
            query.put("payTime" + BaseDaoImpl.lteSqlStr, wxUserQuery.getEndPayTime());
            query.remove("endPayTime");
        }
        if(wxUserQuery.getBeginTopTime() != null) {
            query.put("topTime" + BaseDaoImpl.gteSqlStr, wxUserQuery.getBeginTopTime());
            query.remove("beginTopTime");
        }
        if(wxUserQuery.getEndTopTime() != null) {
            query.put("topTime" + BaseDaoImpl.lteSqlStr, wxUserQuery.getEndTopTime());
            query.remove("endTopTime");
        }

        return query;
    }

    /**
     * 顾客标签拼接
     */
    @Override
    public List<String> getWxUserLable(SysUser wxUser) {
        List<String> lableStrList = new ArrayList<>();
        List<UserLableCentre> centreList = userLableCentreRepository.findByDeletedFalseAndSysUser(wxUser);
        for (UserLableCentre userLableCentre : centreList) {
            lableStrList.add(userLableCentre.getUserLable().getName() + " (" + userLableCentre.getLableCount() + ")");
        }

        return lableStrList;
    }
    /**
     * 顾客标签拼接
     */
    @Override
    public List<Map<String, Object>> getWxUserLableObj(SysUser wxUser) {
        List<Map<String, Object>> lableStrList = new ArrayList<>();
        List<UserLableCentre> centreList = userLableCentreRepository.findByDeletedFalseAndSysUser(wxUser);
        for (UserLableCentre userLableCentre : centreList) {
            Map<String, Object> map = new HashMap<>(16);
            map.put("id", userLableCentre.getUserLable().getId());
            map.put("name", userLableCentre.getUserLable().getName());
            map.put("count", userLableCentre.getLableCount());
            map.put("str", userLableCentre.getUserLable().getName() + " (" + userLableCentre.getLableCount() + ")");
            lableStrList.add(map);
        }

        return lableStrList;
    }

    /**
     * 顾客 会员卡集合
     */
    @Override
    public List<UserCard.Vo> getWxUserCardList(WxUser wxUser, Long orgId) {
        if(wxUser == null) {
            throw new AdminException("获取顾客异常");
        }

        List<UserCard.Vo> returnList = new ArrayList<>();
        List<UserCard> userCardList;
        if(orgId != null) {
            userCardList = userCardRepository.findByDeletedFalseAndWxUserAndOrgId(wxUser, orgId);
        }else {
            userCardList = userCardRepository.findByDeletedFalseAndWxUser(wxUser);
        }
        for (UserCard userCard : userCardList) {
            UserCard.Vo userCardVo = (UserCard.Vo) userCard.toVO();
            if(userCard.getCardType().toString().equals(UserCard.CardType.two.toString())) {
                List<JSONObject> serviceProjectList = new ArrayList<>();
                List<UserCardServiceProjectCentre> centreList = userCardServiceProjectCentreRepository.findByDeletedFalseAndUserCard(userCard);
                for (UserCardServiceProjectCentre centre : centreList) {
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("id", centre.getId());
                    jsonObject.put("count", centre.getCount());
                    jsonObject.put("giveCount", centre.getGiveCount());
                    jsonObject.put("serviceProjectId", centre.getServiceProject().getId());
                    jsonObject.put("serviceProjectName", centre.getServiceProject().getProjectName());
                    serviceProjectList.add(jsonObject);
                }
                userCardVo.setServiceProjectList(serviceProjectList);
            }
            returnList.add(userCardVo);
        }

        return returnList;
    }

    @Override
    public List<Long> statisticsPayUserNum(Long lastTimestamp) {
        StringBuilder sql = new StringBuilder("select o.user_id AS num from orders o");
        sql.append(" where create_time>=");
        sql.append(lastTimestamp);
        sql.append(" GROUP BY o.user_id");
        Query query = entityManager.createNativeQuery(sql.toString());
        List<Long> longList = query.getResultList();
        return longList;
    }

    @Override
    public void initObject(WxUserAddRequest wxUserAddRequest, Long userId) throws AdminException {
        if(!EditCheckUtil.isMobileNO(wxUserAddRequest.getPhone())){throw new AdminException("手机号格式不正确");}
        if(userId == null) {
            if(sysUserRepository.existsByUsername(wxUserAddRequest.getPhone())){throw new AdminException("该手机号已存在");}
        }else {
            SysUser byUsername = sysUserRepository.findByUsername(wxUserAddRequest.getPhone());
            if(byUsername != null) {
                if(!byUsername.getId().toString().equals(userId.toString())) {
                    throw new AdminException("该手机号已存在");
                }
            }
        }
        if(StringUtils.isBlank(wxUserAddRequest.getUserRealCName())) {
            throw new AdminException("请输入用户姓名");
        }
        if(wxUserAddRequest.getOrgId() == null) {
            throw new AdminException("门店为空");
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public WxUser save(WxUser wxUser) throws AdminException {
        if(wxUser.getStatus() == null) {
            wxUser.setStatus(SysUser.Status.on);
        }
        if(StringUtils.isNotBlank(wxUser.getCardNo())) {
            wxUser.setOpenCardTime(System.currentTimeMillis());
        }

        SysUser loginUser = sysUserService.getUser();
        wxUser.setCreateUser(loginUser);
        wxUser.setUpdateUser(loginUser);

        if(wxUser.getOrgId() == null) {
//            if(loginUser.getSection() == null || !(loginUser.getSection() instanceof Org)) {
//                throw new AdminException("登录账号无直属门店, 只属于组织部门");
//            }
//            wxUser.setSection(loginUser.getSection());
            throw new AdminException("门店信息异常");
        }else {
            Org org = dao.get(Org.class, wxUser.getOrgId());
            if(org == null) {
                throw new AdminException(String.format("id: %s 无对应门店信息", wxUser.getOrgId()));
            }
            wxUser.setSection(org);
        }
        wxUser.setCustomerType(WxUser.CustomerType.active);

        // 对象验证
        verifyObject(wxUser);
        if(StringUtils.isBlank(wxUser.getCardNo())) {
            wxUser.setCardNo(AbstractEntity.generyDatetimeAndRandomNum(Constant.ORDERS_SUFF_COUNT));
        }
        wxUser = wxUserRepository.save(wxUser);

        // 关联保存 用户标签
        saveUserLableCentre(wxUser);

        return wxUser;
    }

    /**
     *
     * @param wxUser 非数据库查出对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public WxUser update(WxUser wxUser, boolean isCount) throws AdminException {
        if(wxUser.getOrgId() != null) {
            // 修改门店使用
            Org org = dao.get(Org.class, wxUser.getOrgId());
            if(org == null) {
                throw new AdminException(String.format("id: %s 无对应门店信息", wxUser.getOrgId()));
            }
            wxUser.setSection(org);
        }
        if(StringUtils.isNotBlank(wxUser.getCardNo())) {
            wxUser.setOpenCardTime(System.currentTimeMillis());
        }

        WxUser getWxuser = dao.get(WxUser.class, wxUser.getId());
        if(getWxuser == null) {
            throw new AdminException("编辑顾客id异常");
        }
        Gson gson = bossUserService.getGson();
        WxUser update = gson.fromJson(gson.toJson(getWxuser), WxUser.class);
        BeanUtils.copyProperties(wxUser, update, BeanNullUtil.getNullPropertyNames(wxUser));

        // 对象验证
        verifyObject(update);

        SysUser loginUser = sysUserService.getUser();
        update.setUpdateUser(loginUser);

        update = wxUserRepository.save(update);

        // 是否关联修改标签
        Set<Long> lableIdList = wxUser.getLableIdList();
        List<Long> list_1 = new ArrayList<>(lableIdList);
        List<Long> lableIdCountList = wxUser.getLableIdCuntList();
        List<Long> list_2 = new ArrayList<>();
        if(isCount) {
            if(list_1.size() != lableIdCountList.size()) {
                throw new AdminException("用户标签id与count数目不一致");
            }
        }

        Set<Long> lableIdListUpdate = new HashSet<>();
        if(list_1.size() > 0) {
            List<UserLableCentre> centreList = userLableCentreRepository.findByDeletedFalseAndSysUser(update);
            List<UserLableCentre> delNoCentreList = new ArrayList<>();
            List<UserLableCentre> updateCentreList = new ArrayList<>();
            for (int i = 0; i < list_1.size(); i++) {
                Long aLong = list_1.get(i);
                for (UserLableCentre userLableCentre : centreList) {
                    if(userLableCentre.getUserLable().getId().toString().equals(aLong.toString())) {
                        if(isCount) {
                            if(lableIdCountList.get(i) != null) {
                                userLableCentre.setLableCount(lableIdCountList.get(i).intValue());
                            }else {
                                userLableCentre.setLableCount(userLableCentre.getLableCount() + 1);
                            }
                        }else {
                            userLableCentre.setLableCount(userLableCentre.getLableCount() + 1);
                        }
                        updateCentreList.add(userLableCentre);
                        lableIdListUpdate.add(aLong);
                        list_2.add(lableIdCountList.get(i));

                        delNoCentreList.add(userLableCentre);
                        break;
                    }
                }
            }
            list_1.removeAll(lableIdListUpdate);
            lableIdCountList.removeAll(list_2);
            for (int i = 0; i < list_1.size(); i++) {
                Long aLong = list_1.get(i);
                UserLable userLable = dao.get(UserLable.class, aLong);
                if(userLable == null) {
                    throw new AdminException(String.format("id: %s 无对应标签", aLong));
                }
                if(isCount) {
                    Long aLong1 = lableIdCountList.get(i);
                    if(aLong1 == null) {
                        aLong1 = 1L;
                    }
                    updateCentreList.add(new UserLableCentre(update, userLable, aLong1.intValue()));
                }else {
                    updateCentreList.add(new UserLableCentre(update, userLable, 1));
                }
            }

            centreList.removeAll(delNoCentreList);
            userLableCentreRepository.deleteAll(centreList);
            userLableCentreRepository.saveAll(updateCentreList);
        }

        return update;
    }

    /**
     * 关联保存 用户标签
     */
    private void saveUserLableCentre(WxUser wxUser) {
        Set<Long> lableIdList = wxUser.getLableIdList();
        if(lableIdList != null && lableIdList.size() > 0) {
            List<UserLableCentre> saveUserLableCentreList = new ArrayList<>();
            for (Long aLong : lableIdList) {
                UserLable userLable = dao.get(UserLable.class, aLong);
                if(userLable == null) {
                    throw new AdminException(String.format("id: %s 无对应标签", aLong));
                }
                saveUserLableCentreList.add(new UserLableCentre(wxUser, userLable, 1));
            }
            if(saveUserLableCentreList.size() > 0) {
                userLableCentreRepository.saveAll(saveUserLableCentreList);
            }
        }
    }

    @Override
    public void verifyObject(WxUser wxUser) throws AdminException {
        if(!EditCheckUtil.isMobileNO(wxUser.getMobile())){throw new AdminException("手机号格式不正确");}
        if(wxUser.getId() == null) {
            WxUser get = wxUserRepository.getByDeletedFalseAndMobile(wxUser.getMobile());
            if (get != null) {
                throw new AdminException("该手机号已存在");
            }
        }else {
            WxUser get = wxUserRepository.getByDeletedFalseAndMobile(wxUser.getMobile());
            if(get != null) {
                if(!get.getId().toString().equals(wxUser.getId().toString())) {
                    throw new AdminException("该手机号已存在");
                }
            }
        }
        if(StringUtils.isBlank(wxUser.getUserRealcName())) {
            throw new AdminException("请输入用户姓名");
        }
        if(wxUser.getSection() == null) {
            throw new AdminException("门店为空");
        }
    }

}
